import asyncio
import copy
import json
import queue
import socket
import struct
import threading
import time

from loguru import logger

from other.cfg import Config
from other.status import Status
from other.version import version
from server.Mysql import MySQL


class Tcp:
    def __init__(self):
        self.message_queue = queue.Queue()
        self.websockets = None
        self.client_sockets = []
        self.socket = None
        self.cfg = Config()
        self.st = Status()
        # tt = threading.Thread(target=self.server, args=())
        # tt.start()
        # self.server()

    # websocket消息处理
    async def web_handle(self, data, websocket, connections):
        cmd = None
        self.websockets = connections
        if data['type'] == 'heartbeat':
            cmd = data
        try:
            if cmd is not None:
                cmd = json.dumps(cmd)
                for wb in self.websockets:
                    # 尝试发送消息，如果连接断开则会触发异常
                    await wb.send_text(cmd)
        except Exception as e:
            self.websockets.remove(wb)
            # 捕获异常并处理
            print("WebSocket 连接已断开:", e)
            print('断开异常后的连接', self.websockets)

    async def process_queue(self):
        logger.info(f"开始发送消息给web")
        # cmd = self.message_queue.get()
        cmd = self.message_queue.get()
        logs = copy.deepcopy(cmd)
        logger.info(f"发送给web的队列获取：{cmd}")
        try:
            print('当前连接数', self.websockets)
            if self.websockets is not None and self.websockets != []:
                for wb in self.websockets:
                    # 尝试发送消息，如果连接断开则会触发异常
                    await wb.send_text(json.dumps(cmd))
                    if logs.get('image') is not None:
                        logs.pop('image', None)
                    logger.info(f"websocket_handle发送消息{logs}")
        except Exception as e:
            for item in self.websockets[:]:
                self.websockets.remove(item)
            # self.websockets.remove(wb)
            # 捕获异常并处理
            print("WebSocket 连接已断开:", e)
            print('断开异常后的连接', self.websockets)

    # 数据处理
    def process_data(self, data, get_ip, client_socket):
        # logger.info(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} tcp_recv {data}")
        if data.get('type'):
            if data['type'] == 'type':
                for cc in self.client_sockets:
                    if cc['server'] == client_socket:
                        cc['type'] = 'yy'
            if data['type'] == 'heartbeat':
                self.send_data(data)
            if data['type'] == 'yy':
                cmd = self.get_yy_num()
                self.message_queue.put(cmd)
                # 启动发送消息的任务
                asyncio.run(self.process_queue())
                # self.send_data(cmd)
                # logger.info(f"鹰眼异物消息发送成功: {cmd}")

    # 连接服务
    def server(self):
        host = self.cfg.res['tcp']['host']
        port = int(self.cfg.res['tcp']['port'])
        print(host, port)
        # 创建socket对象
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True:
            try:
                # 绑定地址和端口
                self.socket.bind((host, port))
                logger.info(f"鹰眼Socket服务创建成功")
                break
            except socket.error as msg:
                logger.error(f"鹰眼Socket服务 error: {msg}")
                time.sleep(3)
                continue

        # 开始监听连接
        self.socket.listen(5)
        # logger.info('服务器已启动，等待客户端连接...')

        while True:
            rr = {}
            # 接受客户端连接
            client_socket, client_address = self.socket.accept()
            get_ip = client_socket.getpeername()[0]
            logger.info(f"鹰眼客户端:{get_ip}已连接: {client_address}")
            rr['type'] = None
            rr['ip'] = get_ip
            rr['server'] = client_socket
            self.client_sockets.append(rr)
            print('鹰眼总连接个数:', self.client_sockets)
            handle = threading.Thread(target=self.handle_client, args=(client_socket,))
            handle.start()

    # 消息处理
    def handle_client(self, client_socket):
        try:
            # logger.info("开始处理客户端")
            buffer = b''
            header_received = False
            opening_brace_received = False
            data_length = 0
            st_buffer = b''
            while True:
                res = client_socket.recv(1)
                # print('foreignBody recv')
                if not res:
                    for cc in self.client_sockets:
                        if cc['server'] == client_socket:
                            print(">>>remove", cc)
                            self.client_sockets.remove(cc)
                    print('recv====关闭后的client_sockets', self.client_sockets)
                    break  # 如果没有接收到数据，客户端可能已经断开连接
                st_buffer += res
                if len(st_buffer) > 10:
                    st_buffer = st_buffer[-10:]
                # 检查是否收到了足够长的st_buffer来进行头部验证
                if not header_received and len(st_buffer) >= 10:
                    # 检查头部是否正确
                    if st_buffer[:5] == b'nlane' and st_buffer[::-1][:1] == b'{':
                        data_length = struct.unpack('!I', st_buffer[5:9])[0]
                        header_received = True
                        # 移除已经处理的头部部分
                        buffer = st_buffer[10:]
                # 如果头部被成功接收，开始检查消息体的开始
                if header_received:
                    # 追加剩余的st_buffer到buffer，并重置st_buffer
                    buffer += res
                    if not opening_brace_received and b'{' in buffer:
                        opening_brace_received = True
                        buffer = buffer[buffer.index(b'{'):]  # 裁剪到'{'开始的位置
                    # 检查是否已经接收到完整的数据部分
                    if opening_brace_received and len(buffer) >= data_length and buffer[::-1][:1] == b'}':
                        data = buffer[:data_length]
                        try:
                            json_data = json.loads(data.decode('utf-8'))
                            get_ip = client_socket.getpeername()[0]
                            if json_data['type'] != 'heartbeat':
                                print('接收的信息ip为：', get_ip)
                                logger.info(f"接收鹰眼:{get_ip}的消息成功: {json_data}")
                            tt = threading.Thread(target=self.process_data, args=(json_data, get_ip, client_socket))
                            tt.start()
                        except ValueError as e:
                            logger.error(f"TCP接收失败: {e}")
                        # 清空buffer以接收下一个消息，并重置相关变量
                        buffer = buffer[data_length:]
                        header_received = False
                        opening_brace_received = False
                        data_length = 0
        except Exception as e:
            for cc in self.client_sockets:
                if cc['server'] == client_socket:
                    print(">>>remove", cc)
                    self.client_sockets.remove(cc)
            print('关闭后的client_sockets', self.client_sockets)
            print('recvTCP消息失败', client_socket)
            print('recvTCP消息失败', e)

    def send_data(self, data):
        try:
            # logger.info(f"准备发送数据: {data}")
            # 将数据转换为JSON字符串
            json_str = json.dumps(data, ensure_ascii=False)
            # 添加头部信息
            header = b'nlane' + struct.pack('!I', len(json_str.encode('utf-8')))
            cmd = header + json_str.encode('utf-8')
            for client_socket in self.client_sockets:
                get_ip = client_socket['server'].getpeername()
                # if get_ip[0] == '127.0.0.1':
                #     continue
                # 发送头部信息和数据
                client_socket['server'].sendall(cmd)
                if data['type'] != 'heartbeat':
                    print(f'发送给ip:{get_ip[0]}')
                    print('send', client_socket)
                    logger.info(f"发送给ip:{get_ip[0]}的消息：{data}")
        except Exception as e:
            for cc in self.client_sockets:
                if cc == client_socket:
                    print(">>>remove>>>send", cc)
                    self.client_sockets.remove(cc)
            print('关闭后的client_sockets', self.client_sockets)
            print(e)

    def get_yy_num(self):
        db = MySQL(self.cfg.res['mysql']['database'], 'foreign_body_record')
        sql = f"select count(*) num from `foreign_body_record` where `status`='{self.st.get_status('foreign_body_status', '未处置')}'"
        res = db.gets(sql)
        cmd = {'num': res[0]['num'], 'type': 'yy', 'code': 200}
        return cmd
